<?php

namespace morphos\test\Russian;

use Exception;
use morphos\Russian\NounPluralization;
use PHPUnit\Framework\TestCase;

class NounPluralizationTest extends TestCase
{

    /**
     * @dataProvider pluralizationWordsProvider
     *
     * @param string $word
     * @param $pluralized2
     * @param $pluralized5
     *
     * @throws Exception
     */
    public function testPluralization($word, $pluralized2, $pluralized5)
    {
        // One
        $this->assertEquals($word, NounPluralization::pluralize($word, 1));
        $this->assertEquals($word, NounPluralization::pluralize($word, 101));
        $this->assertEquals($word, NounPluralization::pluralize($word, 201));
        $this->assertEquals($word, NounPluralization::pluralize($word, 1501));
        $this->assertEquals($word, NounPluralization::pluralize($word, 1.0));

        // Two-Four
        $this->assertEquals($pluralized2, NounPluralization::pluralize($word, 2));
        $this->assertEquals($pluralized2, NounPluralization::pluralize($word, 23));
        $this->assertEquals($pluralized2, NounPluralization::pluralize($word, 104));
        $this->assertEquals($pluralized2, NounPluralization::pluralize($word, 1503));
        $this->assertEquals($pluralized2, NounPluralization::pluralize($word, 123.123));

        // Five
        $this->assertEquals($pluralized5, NounPluralization::pluralize($word, 5));
        $this->assertEquals($pluralized5, NounPluralization::pluralize($word, 211));
        $this->assertEquals($pluralized5, NounPluralization::pluralize($word, 520));
        $this->assertEquals($pluralized5, NounPluralization::pluralize($word, 1513));
        $this->assertEquals($pluralized5, NounPluralization::pluralize($word, 10.5));
    }

    public function pluralizationWordsProvider()
    {
        return [
            ['дом', 'дома', 'домов'],
            ['поле', 'поля', 'полей'],
            ['яблоко', 'яблока', 'яблок'],
            ['море', 'моря', 'морей'],
            ['плечо', 'плеча', 'плеч'],
            ['стол', 'стола', 'столов'],
            ['нож', 'ножа', 'ножей'],
            ['плакса', 'плаксы', 'плакс'],
            ['ложка', 'ложки', 'ложек'],
            ['вилка', 'вилки', 'вилок'],
            ['чашка', 'чашки', 'чашек'],
            ['тарелка', 'тарелки', 'тарелок'],
            ['день', 'дня', 'дней'],
            ['ночь', 'ночи', 'ночей'],
            ['ядро', 'ядра', 'ядер'],

            ['рубль', 'рубля', 'рублей'],
            ['фунт', 'фунта', 'фунтов'],
            ['лира', 'лиры', 'лир'],
            ['крона', 'кроны', 'крон'],
            ['юань', 'юаня', 'юаней'],
            ['гривна', 'гривны', 'гривен'],

            // адъективное склонение
            ['ванная', 'ванных', 'ванных'],
            ['прохожий', 'прохожих', 'прохожих'],
        ];
    }

    /**
     * @dataProvider pluralizationWordsWithCaseProvider
     *
     * @param string $word
     * @param $pluralizedOne
     * @param $pluralizedMany
     *
     * @param string $case
     *
     * @throws Exception
     */
    public function testPluralizationWithCase($word, $pluralizedOne, $pluralizedMany, $case)
    {
        // One
        $this->assertEquals($pluralizedOne, NounPluralization::pluralize($word, 1, false, $case));
        $this->assertEquals($pluralizedOne, NounPluralization::pluralize($word, 21, false, $case));
        $this->assertEquals($pluralizedOne, NounPluralization::pluralize($word, 101, false, $case));

        // Many
        $this->assertEquals($pluralizedMany, NounPluralization::pluralize($word, 3, false, $case));
        $this->assertEquals($pluralizedMany, NounPluralization::pluralize($word, 22, false, $case));
        $this->assertEquals($pluralizedMany, NounPluralization::pluralize($word, 60, false, $case));
    }

    public function pluralizationWordsWithCaseProvider()
    {
        return [
            // в ином падеже
            ['год', 'годе', 'годах', 'предложный'],
            ['товар', 'товару', 'товарам', 'дательный'],
        ];
    }

    /**
     * @dataProvider pluralWordsProvider
     */
    public function testPluralInflection($word, $animateness, $inflected)
    {
        $this->assertEquals($inflected, array_values(NounPluralization::getCases($word, $animateness)));
    }

    public function pluralWordsProvider()
    {
        return [
            // 1 склонение
            ['молния', false, ['молния', 'молний', 'молниям', 'молния', 'молниями', 'молниях']],
// TODO: fix first declension
//            ['молния', false, ['молнии', 'молний', 'молниям', 'молнии', 'молниями', 'молниях']],
//            ['дядя', true, ['дяди', 'дядь', 'дядям', 'дядь', 'дядями', 'дядях']],
//            ['судья', true, ['судьи', 'судей', 'судьям', 'судий', 'судьями', 'судьях']],
//            ['мужчина', true, ['мужчины', 'мужчин', 'мужчинам', 'мужчин', 'мужчинами', 'мужчинах']],
            ['тысяча', false, ['тысячи', 'тысяч', 'тысячам', 'тысячи', 'тысячами', 'тысячах']],
            ['копейка', false, ['копейки', 'копеек', 'копейкам', 'копейки', 'копейками', 'копейках']],
            ['батарейка', false, ['батарейки', 'батареек', 'батарейкам', 'батарейки', 'батарейками', 'батарейках']],
            ['улыбка', false, ['улыбки', 'улыбок', 'улыбкам', 'улыбки', 'улыбками', 'улыбках']],
            ['заявка', false, ['заявки', 'заявок', 'заявкам', 'заявки', 'заявками', 'заявках']],
            ['грядка', false, ['грядки', 'грядок', 'грядкам', 'грядки', 'грядками', 'грядках']],
            ['сказка', false, ['сказки', 'сказок', 'сказкам', 'сказки', 'сказками', 'сказках']],
            ['тарелка', false, ['тарелки', 'тарелок', 'тарелкам', 'тарелки', 'тарелками', 'тарелках']],
            ['сумка', false, ['сумки', 'сумок', 'сумкам', 'сумки', 'сумками', 'сумках']],
            ['приманка', false, ['приманки', 'приманок', 'приманкам', 'приманки', 'приманками', 'приманках']],
            ['тряпка', false, ['тряпки', 'тряпок', 'тряпкам', 'тряпки', 'тряпками', 'тряпках']],
            ['марка', false, ['марки', 'марок', 'маркам', 'марки', 'марками', 'марках']],
            ['записка', false, ['записки', 'записок', 'запискам', 'записки', 'записками', 'записках']],
            ['ветка', false, ['ветки', 'веток', 'веткам', 'ветки', 'ветками', 'ветках']],
            ['антропософка', false, ['антропософки', 'антропософок', 'антропософкам', 'антропософки', 'антропософками', 'антропософках']],
            ['книжка', false, ['книжки', 'книжек', 'книжкам', 'книжки', 'книжками', 'книжках']],
            ['клецка', false, ['клецки', 'клецек', 'клецкам', 'клецки', 'клецками', 'клецках']],
            ['крачка', false, ['крачки', 'крачек', 'крачкам', 'крачки', 'крачками', 'крачках']],
            ['чашка', false, ['чашки', 'чашек', 'чашкам', 'чашки', 'чашками', 'чашках']],
            ['юкка', false, ['юкки', 'юкк', 'юккам', 'юкки', 'юкками', 'юкках']],
            ['драка', false, ['драки', 'драк', 'дракам', 'драки', 'драками', 'драках']],
            ['сорока', false, ['сороки', 'сорок', 'сорокам', 'сороки', 'сороками', 'сороках']],
            ['зэка', false, ['зэки', 'зэк', 'зэкам', 'зэки', 'зэками', 'зэках']],
            ['аптека', false, ['аптеки', 'аптек', 'аптекам', 'аптеки', 'аптеками', 'аптеках']],
            ['фабрика', false, ['фабрики', 'фабрик', 'фабрикам', 'фабрики', 'фабриками', 'фабриках']],
            ['подоплёка', false, ['подоплёки', 'подоплёк', 'подоплёкам', 'подоплёки', 'подоплёками', 'подоплёках']],
            ['гадюка', false, ['гадюки', 'гадюк', 'гадюкам', 'гадюки', 'гадюками', 'гадюках']],
            ['кулебяка', false, ['кулебяки', 'кулебяк', 'кулебякам', 'кулебяки', 'кулебяками', 'кулебяках']],
            ['штука', false, ['штуки', 'штук', 'штукам', 'штуки', 'штуками', 'штуках']],

            // 2 склонение
            ['любитель', true, ['любители', 'любителей', 'любителям', 'любителей', 'любителями', 'любителях']],
            ['матрас', false, ['матрасы', 'матрасов', 'матрасам', 'матрасы', 'матрасами', 'матрасах']],
            ['коттедж', false, ['коттеджи', 'коттеджей', 'коттеджам', 'коттеджи', 'коттеджами', 'коттеджах']],
            ['камыш', false, ['камыши', 'камышей', 'камышам', 'камыши', 'камышами', 'камышах']],
            [
                'библиотекарь',
                true,
                ['библиотекари', 'библиотекарей', 'библиотекарям', 'библиотекарей', 'библиотекарями', 'библиотекарях'],
            ],
            [
                'прожектор',
                false,
                ['прожекторы', 'прожекторов', 'прожекторам', 'прожекторы', 'прожекторами', 'прожекторах'],
            ],
            ['пирсинг', false, ['пирсинги', 'пирсингов', 'пирсингам', 'пирсинги', 'пирсингами', 'пирсингах']],
            ['сообщение', false, ['сообщения', 'сообщений', 'сообщениям', 'сообщения', 'сообщениями', 'сообщениях']],
            ['халат', false, ['халаты', 'халатов', 'халатам', 'халаты', 'халатами', 'халатах']],
            ['дом', false, ['дома', 'домов', 'домам', 'дома', 'домами', 'домах']],
            ['склон', false, ['склоны', 'склонов', 'склонам', 'склоны', 'склонами', 'склонах']],
            ['поле', false, ['поля', 'полей', 'полям', 'поля', 'полями', 'полях']],
            ['кирпич', false, ['кирпичи', 'кирпичей', 'кирпичам', 'кирпичи', 'кирпичами', 'кирпичах']],
            ['гвоздь', false, ['гвозди', 'гвоздей', 'гвоздям', 'гвозди', 'гвоздями', 'гвоздях']],
            ['письмо', false, ['письма', 'писем', 'письмам', 'письма', 'письмами', 'письмах']],
            ['пятно', false, ['пятна', 'пятен', 'пятнам', 'пятна', 'пятнами', 'пятнах']],
            ['волчище', false, ['волчища', 'волчищ', 'волчищам', 'волчища', 'волчищами', 'волчищах']],
            ['год', false, ['года', 'лет', 'годам', 'года', 'годами', 'годах']],
            ['месяц', false, ['месяцы', 'месяцев', 'месяцам', 'месяцы', 'месяцами', 'месяцах']],
            ['новость', false, ['новости', 'новостей', 'новостям', 'новости', 'новостями', 'новостях']],
            ['человек', true, ['люди', 'человек', 'людям', 'людей', 'людьми', 'людях']],
            ['песец', true, ['песцы', 'песцов', 'песцам', 'песцов', 'песцами', 'песцах']],
            [
                'руководитель',
                true,
                ['руководители', 'руководителей', 'руководителям', 'руководителей', 'руководителями', 'руководителях'],
            ],
            ['голосование', true, ['голосования', 'голосований', 'голосованиям', 'голосований', 'голосованиями', 'голосованиях']],
            ['дерево', false, ['деревья', 'деревьев', 'деревьям', 'деревья', 'деревьями', 'деревьях']],
            ['гений', true, ['гения', 'гениев', 'гениям', 'гениев', 'гениями', 'гениях']],

            // 3 склонение
            ['лошадь', false, ['лошади', 'лошадей', 'лошадям', 'лошади', 'лошадями', 'лошадях']],
            ['тень', false, ['тени', 'теней', 'теням', 'тени', 'тенями', 'тенях']],
            ['ночь', false, ['ночи', 'ночей', 'ночам', 'ночи', 'ночами', 'ночах']],

            // Адъективное склонение
            // мужской род
            ['выходной', false, ['выходные', 'выходных', 'выходным', 'выходные', 'выходными', 'выходных']],
            [
                'двугривенный',
                false,
                ['двугривенные', 'двугривенных', 'двугривенным', 'двугривенные', 'двугривенными', 'двугривенных'],
            ],
            ['рабочий', true, ['рабочие', 'рабочих', 'рабочим', 'рабочих', 'рабочими', 'рабочих']],
            // средний род
            ['животное', true, ['животные', 'животных', 'животным', 'животных', 'животными', 'животных']],
            [
                'подлежащее',
                false,
                ['подлежащие', 'подлежащих', 'подлежащим', 'подлежащие', 'подлежащими', 'подлежащих'],
            ],
            // женский род
            ['запятая', false, ['запятые', 'запятых', 'запятым', 'запятые', 'запятыми', 'запятых']],
            ['горничная', true, ['горничные', 'горничных', 'горничным', 'горничных', 'горничными', 'горничных']],
            ['заведующая', true, ['заведующие', 'заведующих', 'заведующим', 'заведующих', 'заведующими', 'заведующих']],
        ];
    }
}
